﻿using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace MyLib
{
    /// <summary>
    /// 通用TCP服务器
    /// 
    /// FPSMgr 需要一个TCP服务器供 FPSServer连接发送消息
    /// 类似一GRPC 低配版本 根据协议决定处理函数
    /// 而不是根据 rpc 来确定处理的 Request Response
    /// </summary>
    public class TcpNetServer
    {
        public ActorSynchronizationContext mainLoop;
        public int port;
        /// <summary>
        /// 新的链接回调  主线程执行
        /// </summary>
        public System.Action<TcpNetConnect> OnNewConnect;


        public bool stop = false;
        TcpListener tcpListener;
        private List<TcpNetConnect> connects = new List<TcpNetConnect>();
        /// <summary>
        /// 回到同步上下文中 
        /// ActorSynchronizationContext
        /// 永远在当前线程执行
        /// </summary>
        /// <returns></returns>
        public async Task Start(bool noDelay=false)
        {
            await mainLoop;
            try
            {
                tcpListener = new TcpListener(IPAddress.Any, port);
                tcpListener.Server.NoDelay = noDelay;
                tcpListener.Start();
            }catch(Exception exp)
            {
                LogHelper.Log2("TCP StartError:"+exp.ToString());
                return;
            }

            while (!stop)
            {
                TcpClient tcpClient = null;
                try
                {
                    tcpClient = await tcpListener.AcceptTcpClientAsync();
                }
                catch (Exception exp)
                {
                    LogHelper.Log2("AcceptTcpClient:" + exp.ToString());
                }
                if(tcpClient != null)
                {
                    AddAgent(tcpClient);
                }
            }
        }

        private void AddAgent(TcpClient client)
        {
            var c = new TcpNetConnect()
            {
                tcpClient = client,
                //netServer = this,
                mainLoop = mainLoop,
            };

            c.OnNetClosed = () =>
            {
                connects.Remove(c);
            };
            connects.Add(c);
            if (OnNewConnect != null) OnNewConnect(c);
            c.Start();
        }
    }
}
